#pragma once
#include <iostream>
#include <vector>
#include "Sem.hpp"

namespace RingBufferModule
{
    using namespace SemModule;

    template <class T>
    class RingBuffer
    {
    public:
        RingBuffer(int cap)
            : _cap(cap)
            , _ring(cap)
            , _c_step(0)
            , _p_step(0)
            ,_datasem(0)
            ,_spacesem(cap)
        {
        }
        void Equeue(const T &in)
        {
            // 生产者
            _spacesem.P();
            
            _ring[_p_step] = in; //生产完毕
            _p_step++;
            _p_step %= _cap;     //维持环形特性

            _datasem.V();
        }
        void Pop(T *out)
        {
            // 消费者
            _datasem.P();

            *out = _ring[_c_step];
            _c_step++;
            _c_step %= _cap;

            _spacesem.V();
        }
        ~RingBuffer()
        {
            
        }

    private:
        std::vector<T> _ring; // 环(临界资源)
        int _cap;             // 总容量
        int _c_step;          // 消费者位置
        int _p_step;          // 生产者位置

        Sem _datasem;  // 数据信号量
        Sem _spacesem; // 空间信号量
    };
}